#include "interfaceclass.h"

QFile ParseProtocol::m_file;
PR ParseProtocol::m_protocol;
QMap<QString, PR> ParseProtocol::m_mprotocol;


QHash<QString, QVector<myfunction>> InterfaceManager::m_funcset = {};


bool OracleDB::m_blsConn = false;
QSqlDatabase OracleDB::m_db = QSqlDatabase::addDatabase("QOCI");


ParseProtocol::ParseProtocol(const QString& filename) {
    m_file.setFileName(filename);
    if(!m_file.open(QFile::ReadOnly)) {
        cout << "FileName: " << filename << "：打开文件失败，请重试...";
    }
    m_mothod = new MeteoMothod;
    if(m_mprotocol.empty()) {
        ParseProtocol::ReadXmlProtocol();
    }
}

ParseProtocol::~ParseProtocol() {
    if(m_file.isOpen()){
        m_file.close();
    }
    if(m_mothod != nullptr) {
        delete m_mothod;
        m_mothod = nullptr;
    }
}

void ParseProtocol::ReadXmlProtocol() {
    QDomDocument doc;
    if(!doc.setContent(&m_file)) {
        m_file.close();
    }

    QDomElement root = doc.documentElement();
    QDomNode node = root.firstChild();
    while(!node.isNull()) {
        m_protocol.vpf.clear();
        m_protocol.vpp.clear();
        QString name = node.toElement().attribute("name");
        if(node.isElement()) {
            QDomNode childnode = node.firstChild();
            while(!childnode.isNull()) {
                QDomElement nodeElement = childnode.toElement();
                QDomNodeList list = nodeElement.childNodes();

                if(nodeElement.tagName() == "ProtocolProperty") {
                    PP property;
                    for(int i = 0; i < list.count(); ++i) {
                        QDomNode nodeIndex = list.at(i);
                        if(childnode.isElement()) {
                            property.key = nodeIndex.toElement().attribute("key");
                            property.value = nodeIndex.toElement().attribute("value");
                            m_protocol.vpp.append(property);
                        }
                    }
                }
                else {
                    PF pfiled;
                    for(int i = 0; i < list.count(); ++i) {
                        QDomNode nodeIndex = list.at(i);
                        QString str = nodeIndex.nodeName();
                        if(childnode.isElement() && (str == "MeteoProtocol")) {
                            pfiled.filedName = nodeIndex.toElement().attribute("filedName");
                            pfiled.filedType = nodeIndex.toElement().attribute("filedType");
                            pfiled.filedMethod = nodeIndex.toElement().attribute("filedMethod");
                            pfiled.filedMeasurement = nodeIndex.toElement().attribute("filedMeasurement");
                            pfiled.filedInstruction = nodeIndex.toElement().attribute("filedInstruction");
                            m_protocol.vpf.append(pfiled);
                        }
                    }
                }
                childnode = childnode.nextSibling();
            }

        }
        if(name != "")
            m_mprotocol.insert(name, m_protocol);
        node = node.nextSibling();
    }
}

void ParseProtocol::AnalyticProcess(const QByteArray& data, const int i) {
    if(m_mprotocol[m_mesflag].vpf.at(i).filedType == "ushort") {
        if(m_pos + 1 >= data.size()) {
            m_pos += 2;
            cout << "数据解析完成，但数据与报文段非完美匹配！";
            return;
        }
        QByteArray arg;
        arg.resize(2);
        arg[0] = data[m_pos];
        arg[1] = data[m_pos + 1];
        m_prodata.rowValue = m_mothod->ushort2run(m_mprotocol[m_mesflag].vpf.at(i).filedMethod, arg);
        m_pos += 2;
    }
    else if(m_mprotocol[m_mesflag].vpf.at(i).filedType == "short") {
        if(m_pos + 1 >= data.size()) {
            m_pos += 2;
            cout << "数据解析完成，但数据与报文段非完美匹配！";
            return;
        }
        QByteArray arg;
        arg.resize(2);
        arg[0] = data[m_pos];
        arg[1] = data[m_pos + 1];
        m_prodata.rowValue = m_mothod->short2run(m_mprotocol[m_mesflag].vpf.at(i).filedMethod, arg);
        m_pos += 2;
    }
    else if(m_mprotocol[m_mesflag].vpf.at(i).filedType == "uint") {
        if(m_pos + 3 >= data.size()) {
            m_pos += 4;
            cout << "数据解析完成，但数据与报文段非完美匹配！";
            return;
        }
        QByteArray arg;
        arg.resize(4);
        arg[0] = data[m_pos];
        arg[1] = data[m_pos + 1];
        arg[2] = data[m_pos + 2];
        arg[3] = data[m_pos + 3];
        m_prodata.rowValue = m_mothod->uint2run(m_mprotocol[m_mesflag].vpf.at(i).filedMethod, arg);
        m_pos += 4;
    }
    else if(m_mprotocol[m_mesflag].vpf.at(i).filedType == "int") {
        if(m_pos + 3 >= data.size()) {
            m_pos += 4;
            cout << "数据解析完成，但数据与报文段非完美匹配！";
            return;
        }
        QByteArray arg;
        arg.resize(4);
        arg[0] = data[m_pos];
        arg[1] = data[m_pos + 1];
        arg[2] = data[m_pos + 2];
        arg[3] = data[m_pos + 3];
        m_prodata.rowValue = m_mothod->int2run(m_mprotocol[m_mesflag].vpf.at(i).filedMethod, arg);
        m_pos += 4;
    }
    else if(m_mprotocol[m_mesflag].vpf.at(i).filedType == "byte") {
        QByteArray arg;
        arg.resize(1);
        arg[0] = data[m_pos];
        m_prodata.rowValue = m_mothod->byte2run(m_mprotocol[m_mesflag].vpf.at(i).filedMethod, arg);
        ++m_pos;
    }
    else if(m_mprotocol[m_mesflag].vpf.at(i).filedType == "string") {
        int size = m_mprotocol[m_mesflag].vpf.at(i).filedMethod.toInt();
        if(m_pos + size - 1 >= data.size()) {
            m_pos += size;
            cout << "数据解析完成，但数据与报文段非完美匹配！";
            return;
        }
        QByteArray arg;
        arg.resize(size);
        for(int i = 0; i < size; ++i)
            arg[i] = data[m_pos + i];
        m_pos += size;
        m_prodata.rowValue = m_mothod->string2run(arg);
    }

    if(m_mprotocol[m_mesflag].vpf.at(i).filedMeasurement == "-") {
        m_prodata.rowDisplay = "";
    }
    else {
        m_prodata.rowDisplay = m_mprotocol[m_mesflag].vpf.at(i).filedMeasurement;
    }

    m_prodata.rowInstruction = m_mprotocol[m_mesflag].vpf.at(i).filedInstruction;
    m_vprodata.append(m_prodata);
}

VecPD ParseProtocol::ParsePacketData(const QByteArray& data, const int dataLen) {
    m_vprodata.clear();
    if(m_mprotocol.empty()) {
        cout << "协议为空～";
        return m_vprodata;
    }
    if(data.size() == 0) {
        cout << "数据为空～";
        return m_vprodata;
    }

    m_ok = false;
    bool ok = true;
    m_mesflag = "";
    for(auto it = m_mprotocol.begin(); it != m_mprotocol.end(); ++it) {
        QString flag = it.key();
        for(int i = 0; i < it.value().vpp.size(); ++i) {
            int index = it.value().vpp.at(i).key.toInt();
            if(dataLen - 1 <= index) {
                flag = "";
                break;
            }
            QByteArray tmpda;
            tmpda.resize(1);
            tmpda[0] = data[index];
            if(tmpda.toHex().toInt(&m_ok, 16) != it.value().vpp.at(i).value.toInt(&m_ok, 16)) {
                if(!m_ok) {
                    cout << "解析 判定 失败！";
                }
                m_ok = false;
                flag = "";
                break;
            }
        }
        if(flag != "") {
            m_mesflag = flag;
            break;
        }
    }
    if(m_mesflag == "") {
        cout << "解析完成，未检测到报文协议与之对应～";
        return m_vprodata;
    }

    m_pos = 0;
    for(int i = 0; i < m_mprotocol[m_mesflag].vpf.size() && m_pos < data.size(); ++i) {
        if(m_pos >= dataLen) {
            ok = false;
            cout << "数据解析完成，但数据与报文段非完美匹配！";
            break;
        }
        if(m_mprotocol[m_mesflag].vpf.at(i).filedType == "") {
            continue;
        }

        m_prodata.rowNum = "";
        m_prodata.rowProperty = "";
        m_prodata.rowValue = "";
        m_prodata.rowDisplay = "";
        m_prodata.rowInstruction = "";

        m_prodata.rowNum = QString::number(i + 1);
        m_prodata.rowProperty = m_mprotocol[m_mesflag].vpf.at(i).filedName;

        if(m_mprotocol[m_mesflag].vpf.at(i).filedMethod == "LOOP BEGIN") {
            AnalyticProcess(data, i);
            int sumpos = 0;
            i += 1;
            int num4value = m_prodata.rowValue.toInt();
            int num4elem = 0;
            int tmp = i;
            while(m_mprotocol[m_mesflag].vpf.at(tmp).filedMethod != "LOOP END"
                  && m_mprotocol[m_mesflag].vpf.size() > tmp) {
                if(m_mprotocol[m_mesflag].vpf.at(tmp).filedType == "int" ||
                        m_mprotocol[m_mesflag].vpf.at(tmp).filedType == "uint") {
                    sumpos += 4;
                }
                else if(m_mprotocol[m_mesflag].vpf.at(tmp).filedType == "short" ||
                        m_mprotocol[m_mesflag].vpf.at(tmp).filedType == "ushort") {
                    sumpos += 2;
                }
                else if(m_mprotocol[m_mesflag].vpf.at(tmp).filedType == "byte") {
                    sumpos += 1;
                }
                else if(m_mprotocol[m_mesflag].vpf.at(tmp).filedType == "string") {
                    sumpos += m_mprotocol[m_mesflag].vpf.at(tmp).filedMethod.toInt();
                }
                num4elem++;
                tmp++;
            }
            if((m_pos + sumpos * num4value) > dataLen) {
                cout << "LOOP BEGIN error: 请检查循环次数！";
                goto SUMPOSERROR;
            }
            for(int k = 0; k < num4value; ++k) {
                for(int j = 0; j < num4elem; ++j) {
                    QString str = QString::number(k + 1);
                    QString name = m_mprotocol[m_mesflag].vpf.at(i + j).filedName;
                    name.replace(name.indexOf('n'), 1, str);
                    m_prodata.rowProperty = name;
                    AnalyticProcess(data, i + j);
                }
            }
            i += num4elem - 1;
        }
        else {
            AnalyticProcess(data, i);
        }
    }

SUMPOSERROR:
    if(m_pos >= dataLen - 1 && ok == true) {
        cout << "报文：" + m_mesflag + " 数据已经解析完成！";
    }

    if(m_pos < dataLen - 1) {
        cout <<"报文解析完成，data仍未结束！";
    }
    return m_vprodata;
}

MeteoMothod::~MeteoMothod() {}
bool MeteoMothod::m_ok = false;

template<typename T>
QString toBinString(const T& value, const QString& type) {
    QString str = QString::number(value, 2);
    int num;
    if(type == "byte") {
        num = 8 - str.size();
        if(num > 0) {
            QString tmp(num, '0');
            str.push_front(tmp);
        }
    }
    else if(type == "short" || type == "ushort") {
        num = 16 - str.size();
        if(num > 0) {
            QString tmp(num, '0');
            str.push_front(tmp);
        }
    }
    else if(type == "int" || type == "uint") {
        num = 32 - str.size();
        if(num > 0) {
            QString tmp(num, '0');
            str.push_front(tmp);
        }
    }
    return str;
}

template<typename T>
T Complement2Dec(const QByteArray& value) {
    bool ok;
    T tmp = value.toHex().toLong(&ok, 16);
    QString bin = QString::number(tmp, 2);
    if(bin.at(0) == "0" || bin.size() < 32) {
        return tmp;
    }
    else {
        bin.replace(0, 1, "0");
        for(int i = 1; i < bin.size(); ++i) {
            if(bin.at(i) == "0")
                bin.replace(i, 1, "1");
            else
                bin.replace(i, 1, "0");
        }
        for(int i = bin.size() - 1; i >= 0; --i) {
            if(bin.at(i) == "0") {
                bin.replace(i, 1,"1");
                break;
            }
            bin.replace(i, 1, "0");
        }
    }
    T res = bin.toInt(nullptr, 2) * (-1);
    return res;
}

template<typename T>
QString MeteoMothoded(const T tmp, const QByteArray& value, const QString& mothod, const QString& type) {
    if(mothod == "-") {
        return QString::number(tmp);
    }
    else if(mothod == "BIN") {
        return toBinString<T>(tmp, type);
    }
    else if(mothod == "ASCII" || mothod == "ASCII-8") {
        QString res = value;
        return res;
    }
    else if(mothod == "bcd" || mothod == "BCD") {
        int a = tmp / 16;
        int b = tmp % 16;
        return QString::number(a) + QString::number(b);
    }
    else if(mothod == "LOOP BEGIN") {
        return QString::number(tmp);
    }
    else if(mothod.contains('-')) {
        QString res;
        QVector<int> vi;
        QVector<QString> vs;
        QString bin = toBinString<T>(tmp, type);
        for(int i = 0; i < mothod.size(); ++i) {
            if(mothod.at(i) == '-') {
                QString tmp = mothod.at(i - 1);
                vi.push_back(tmp.toInt());
            }
        }
        QStringList list1 = mothod.split('-');
        for(int i = 1; i < list1.size(); ++i) {
            QString tmp = list1.at(i);
            QStringList list2 = tmp.split('(');
            vs.push_back(list2.at(0));
        }

        for(int i = 0; i < vi.size() && i < vs.size(); ++i) {
            if(bin.at(bin.size() - 1 - i) == '1') {
                res += vs.at(i) + ":有效";
            }
            else {
                res += vs.at(i) + ":无效";
            }
            if(i != vi.size() - 1 || i != vs.size() - 1) {
                res += "  ";
            }
        }
        return res;
    }

    if(!mothod.contains('^')) {
        double v = mothod.toDouble();
        return QString::number(1.0 * (tmp * v));
    }
    else if(mothod.contains('^')) {
        if(mothod.contains('/')) {
            QStringList strlista = mothod.split('/');
            QString stra = strlista.at(0);
            T numa = stra.toUInt();
            QString strb = strlista.at(1);
            QStringList strlistb = strb.split('^');
            QString strc = strlistb.at(0);
            T numc = strc.toInt();
            QString strd = strlistb.at(1);
            T numd = strd.toInt();
            return QString::number(1.0 * tmp * (numa / (pow(numc, numd))));
        }
        else {
            return QString::number(tmp) + mothod;
        }
    }
    else {
        return QString::number(tmp * mothod.toInt());
    }

    return "";
}

QString MeteoMothod::uint2run(const QString& mothod, const QByteArray& value){
    uint32_t tmp = value.toHex().toUInt(&m_ok, 16);
    tmp = ntohl(tmp);
    if(mothod == "IP") {
        struct in_addr in;
        in.s_addr = tmp;
        return inet_ntoa(in);
    }
    return MeteoMothoded<uint32_t>(tmp, value, mothod, "uint");
}

QString MeteoMothod::int2run(const QString& mothod, const QByteArray& value){
    int32_t tmp = Complement2Dec<int32_t>(value);
    tmp = ntohl(tmp);
    return MeteoMothoded<int32_t>(tmp, value, mothod, "int");
}

QString MeteoMothod::ushort2run(const QString& mothod, const QByteArray& value) {
    uint16_t tmp = value.toHex().toUShort(&m_ok, 16);
    tmp = ntohs(tmp);
    return MeteoMothoded<uint16_t>(tmp, value, mothod, "ushort");
}

QString MeteoMothod::short2run(const QString& mothod, const QByteArray& value) {
    int16_t tmp = value.toHex().toShort(&m_ok, 16);
    tmp = ntohs(tmp);
    return MeteoMothoded<int16_t>(tmp, value, mothod, "short");
}

QString MeteoMothod::byte2run(const QString& mothod, const QByteArray& value) {
    uint8_t tmp = value.toHex().toInt(&m_ok, 16);
    return MeteoMothoded<uint8_t>(tmp, value, mothod, "byte");
}

QString MeteoMothod::string2run(const QByteArray& value){
    QString res = value;
    return res;
}


QFile ConvertData::m_file;
QMap<QString, PR> ConvertData::m_protocol;

ConvertData::ConvertData(const QString& filename, const QStringList& rowdata)
    :m_rowdata(rowdata) {
    if(m_protocol.empty()) {
        ConvertData::ReadXmlProtocol(filename);
    }
    m_prosize = 0;
    m_pos = 1;
    m_mothod = new ConverMothod;
}

void ConvertData::ReadXmlProtocol(const QString& filename) {
    m_file.setFileName(filename);
    if(!m_file.open(QFile::ReadOnly)) {
        cout << "FileName: " << filename << "：打开文件失败，请重试...";
    }
    QDomDocument doc;
    if(!doc.setContent(&m_file)) {
        m_file.close();
    }

    PR protocol;
    QDomElement root = doc.documentElement();
    QDomNode node = root.firstChild();
    while(!node.isNull()) {
        protocol.vpf.clear();
        protocol.vpp.clear();
        QString name = node.toElement().attribute("name");
        if(node.isElement()) {
            QDomNode childnode = node.firstChild();
            while(!childnode.isNull()) {
                QDomElement nodeElement = childnode.toElement();
                QDomNodeList list = nodeElement.childNodes();

                if(nodeElement.tagName() == "ProtocolProperty") {
                    PP property;
                    for(int i = 0; i < list.count(); ++i) {
                        QDomNode nodeIndex = list.at(i);
                        if(childnode.isElement()) {
                            property.key = nodeIndex.toElement().attribute("key");
                            property.value = nodeIndex.toElement().attribute("value");
                            protocol.vpp.append(property);
                        }
                    }
                }
                else {
                    PF pfiled;
                    for(int i = 0; i < list.count(); ++i) {
                        QDomNode nodeIndex = list.at(i);
                        QString str = nodeIndex.nodeName();
                        if(childnode.isElement() && (str == "MeteoProtocol")) {
                            pfiled.filedName = nodeIndex.toElement().attribute("filedName");
                            pfiled.filedType = nodeIndex.toElement().attribute("filedType");
                            pfiled.filedMethod = nodeIndex.toElement().attribute("filedMethod");
                            pfiled.filedMeasurement = nodeIndex.toElement().attribute("filedMeasurement");
                            pfiled.filedInstruction = nodeIndex.toElement().attribute("filedInstruction");
                            protocol.vpf.append(pfiled);
                        }
                    }
                }
                childnode = childnode.nextSibling();
            }

        }
        if(name != "")
            m_protocol.insert(name, protocol);
        node = node.nextSibling();
    }
}

ConverMothod::ConverMothod() {}

ConverMothod::~ConverMothod() {}

template<typename T>
T RunMothod(T& num, const QString& value, const QString& mothod) {
    bool ok;
    if(mothod == "-" || mothod == "1" || mothod == "LOOP BEGIN") {
        num = value.toLong();
    }
    else if(mothod == "BIN") {
        num = value.toLong(&ok, 2);
    }
    else if(mothod.contains('.') && !mothod.contains('-')) {
        num = value.toDouble() / mothod.toDouble();
    }
    else if(mothod.contains('/')) {
        QStringList list = mothod.split('/');
        QString tmp = list.at(0);
        QString str = list.at(1);
        if(list.at(1).contains('^')) {
            QStringList list1 = str.split('^');
            QString numc = list1.at(0);
            QString numd = list1.at(1);
            long long numm = value.toDouble() * (pow(numc.toInt(), numd.toInt()));
            num = numm / tmp.toInt();
        }
    }
    else if(mothod.contains('-')) {
        QString res;
        QStringList list = value.split("  ");
        for(int i = 0; i < list.size(); ++i) {
            QString str = list.at(i);
            if(str.contains("有效")) {
                res.push_front('1');
            }
            else {
                res.push_front('0');
            }
        }
        num = res.toInt(&ok, 2);
    }
    else if(mothod == "IP") {
        struct in_addr in;
        QByteArray ba;
        ba.append(value);
        const char* ip = ba.data();
        inet_aton(ip, &in);
        num = in.s_addr;
    }
    else {
        num = value.toInt();
    }
    return num;
}

QByteArray ConverMothod::byte2run(const QString& value, const QString& mothod) {
    m_data.clear();
    m_data.resize(1);
    uint8_t num;
    num = RunMothod<uint8_t>(num, value, mothod);
    QDataStream qs(&m_data, QIODevice::ReadWrite);
    qs << num;
    return m_data;
}

QByteArray ConverMothod::short2run(const QString& value, const QString& mothod) {
    m_data.clear();
    m_data.resize(2);
    int16_t num;
    num = RunMothod<int16_t>(num, value, mothod);
    QDataStream qs(&m_data, QIODevice::ReadWrite);
    num = htons(num);
    qs << num;

    return m_data;
}

QByteArray ConverMothod::ushort2run(const QString& value, const QString& mothod) {
    m_data.clear();
    m_data.resize(2);
    uint16_t num;
    num = RunMothod<uint16_t>(num, value, mothod);
    QDataStream qs(&m_data, QIODevice::ReadWrite);
    num = htons(num);
    qs << num;
    return m_data;
}

QByteArray ConverMothod::int2run(const QString& value, const QString& mothod) {
    m_data.clear();
    m_data.resize(4);
    int32_t num;
    num = RunMothod<int32_t>(num, value, mothod);
    QDataStream qs(&m_data, QIODevice::ReadWrite);
    num = htonl(num);
    qs << num;
    return m_data;
}

QByteArray ConverMothod::uint2run(const QString& value, const QString& mothod) {
    m_data.clear();
    m_data.resize(4);
    uint32_t num;
    num = RunMothod<uint32_t>(num, value, mothod);
    QDataStream qs(&m_data, QIODevice::ReadWrite);
    num = htonl(num);
    qs << num;
    return m_data;
}

QByteArray ConverMothod::string2run(const QString& value, const int& n) {
    m_data.clear();
    m_data.resize(n);
    m_data = value.toLatin1().toHex();
    QByteArray tmpbta = "00";
    while(m_data.size() < n) {
        m_data.push_back(tmpbta);
    }
    return m_data;
}

ConvertData::~ConvertData() {
    if(m_file.isOpen()){
        m_file.close();
    }
    if(m_mothod != nullptr) {
        delete m_mothod;
        m_mothod = nullptr;
    }
}

int ConvertData::getProSize() {
    return m_prosize;
}

void ConvertData::ConvertRowData() {
    if(m_rowdata.empty() || m_rowdata.size() < 2) {
        cout << "无数据可封装";
        return;
    }
    VTM vtm;
    m_proname = m_rowdata.at(0);
    bool success = false;
    for(auto it = m_protocol.begin(); it != m_protocol.end(); ++it) {
        if(it.key() == m_proname) {
            success = true;
            break;
        }
    }
    if(!success) {
        cout << "不存在与原始数据对应的协议，无法进行数据转换！";
        return;
    }

    int num4value = 0;
    int num4elem = 0;

    for(int i = 0; i < m_protocol[m_proname].vpf.size(); ++i) {
        vtm.value = m_rowdata.at(m_pos);
        vtm.type = m_protocol[m_proname].vpf.at(i).filedType;
        vtm.mothod = m_protocol[m_proname].vpf.at(i).filedMethod;
        m_vtm.push_back(vtm);

        if(m_protocol[m_proname].vpf.at(i).filedMethod == "LOOP BEGIN") {
            QString tmp = m_rowdata.at(m_pos);
            num4value = tmp.toInt();
            ++m_pos;
            if(m_pos >= m_rowdata.size()) {
                break;
            }
            ++i;
            int j = i;
            while(m_protocol[m_proname].vpf.at(j).filedMethod != "LOOP END"
                  && m_protocol[m_proname].vpf.size() > j) {
                num4elem++;
                j++;
            }
            for(int m = 0; m < num4value; ++m) {
                for(int n = i; n < i + num4elem; ++n) {
                    vtm.value = m_rowdata.at(m_pos);
                    vtm.type = m_protocol[m_proname].vpf.at(n).filedType;
                    vtm.mothod = m_protocol[m_proname].vpf.at(n).filedMethod;
                    m_vtm.push_back(vtm);
                    m_pos++;
                    if(m_pos >= m_rowdata.size()) {
                        break;
                    }
                }
            }
            m_pos--;
            i += num4elem;
        }
        m_pos++;
        if(m_pos >= m_rowdata.size()) {
            break;
        }
    }

    int num4protocol = 0;
    for(int i = 0; i < m_protocol[m_proname].vpf.size(); ++i) {
        if(m_protocol[m_proname].vpf.at(i).filedType != "")
            num4protocol++;
    }

    if(num4protocol + (num4value - 1) * num4elem == m_rowdata.size() - 1) {
        cout << "数据与协议完美匹配";
    }
    else if(num4protocol + (num4value - 1) * num4elem > m_rowdata.size() - 1) {
        cout << "数据太少，协议未全部被使用";
    }
    else {
        cout << "数据太多，协议不能够完全匹配";
    }

    if(m_pos == m_rowdata.size()) {
        cout << "数据已被完全转换";
    }
    else {
        cout << "数据未被完全转换";
    }
}

QByteArray ConvertData::ConvertNewData() {
    m_data.clear();
    ConvertRowData();
    for(int i = 0; i < m_vtm.size(); ++i) {
        if(m_vtm.at(i).type == "byte") {
            m_prosize += 1;
        }
        else if(m_vtm.at(i).type == "short" || m_vtm.at(i).type == "ushort") {
            m_prosize += 2;
        }
        else if(m_vtm.at(i).type == "int" || m_vtm.at(i).type == "uint") {
            m_prosize += 4;
        }
        else if(m_vtm.at(i).type == "string") {
            m_prosize += m_vtm.at(i).mothod.toInt();
        }
    }

    for(int i = 0; i < m_vtm.size(); ++i) {
        if(m_vtm.at(i).type == "byte") {
            m_data.push_back(m_mothod->byte2run(m_vtm.at(i).value, m_vtm.at(i).mothod));
        }
        else if(m_vtm.at(i).type == "short") {
            m_data.push_back(m_mothod->short2run(m_vtm.at(i).value, m_vtm.at(i).mothod));
        }
        else if(m_vtm.at(i).type == "ushort") {
            m_data.push_back(m_mothod->ushort2run(m_vtm.at(i).value, m_vtm.at(i).mothod));
        }
        else if(m_vtm.at(i).type == "int") {
            m_data.push_back(m_mothod->int2run(m_vtm.at(i).value, m_vtm.at(i).mothod));
        }
        else if(m_vtm.at(i).type == "uint") {
            m_data.push_back(m_mothod->uint2run(m_vtm.at(i).value, m_vtm.at(i).mothod));
        }
        else if(m_vtm.at(i).type == "ushort") {
            m_data.push_back(m_mothod->ushort2run(m_vtm.at(i).value, m_vtm.at(i).mothod));
        }
        else if(m_vtm.at(i).type == "string") {
            m_data.push_back(m_mothod->string2run(m_vtm.at(i).value, m_vtm.at(i).mothod.toInt()));
        }
    }
    return m_data;
}

void OracleDB::connectOracleDB(const QString& ip, const QString& port,
                               const QString& username, const QString& password) {
    m_db.setHostName(ip);
    m_db.setPort(port.toInt());
    m_db.setDatabaseName("orcl");
    m_db.setUserName(username);
    m_db.setPassword(password);
    if(m_db.open()) {
        cout << "Oracle u8 连接成功！";
        m_blsConn = true;
    }
    else {
        cout << "Oracle u8 faild!";
        m_blsConn = false;
    }
}

OracleDB::OracleDB(const QString& filename) {
    if(!m_blsConn) {
        QSettings setread(filename, QSettings::IniFormat);
        QString ip = setread.value("OracleDB/ip").toString();
        QString port = setread.value("OracleDB/port").toString();
        QString username = setread.value("OracleDB/username").toString();
        QString password = setread.value("OracleDB/password").toString();
        connectOracleDB(ip, port, username, password);
    }
}

VVQ OracleDB::sqlQuery(const QString& sentence) {
    QVector<QVariant> tmpres;;
    m_res.clear();
    m_ok = m_query.exec(sentence);
    if(m_ok) {
        QSqlRecord rec = m_query.record();
        int col = rec.count();    // 结果集列数
        int row = 0;              // 结果集行数
        for(int i = 0; i < col; ++i)
        {
            tmpres.push_back(rec.fieldName(i));
        }
        m_res.push_back(tmpres);

        while(m_query.next()) {
            row++;
            tmpres.clear();
            for(int i = 0; i < col; ++i) {
                tmpres.push_back(m_query.value(i));
            }
            m_res.push_back(tmpres);
        }
        cout << "语句：" << sentence << " 执行成功！";
    }
    else {
        cout << "语句：" << sentence << " 执行失败！";
    }
    return m_res;
}

bool OracleDB::sqlOpt(const QString& sentence) {
    m_ok = m_query.exec(sentence);
    if(m_ok) {
        cout << "语句：" << sentence << " 执行成功！";
    }
    else {
        cout << "语句：" << sentence << " 执行失败！";
    }
    return m_ok;
}

QSqlQuery OracleDB::getSqlQuery() {
    return m_query;
}


///////////////////////////////////////////////////////////////////


InterfaceManager::InterfaceManager() {
    m_pub = new Publisher;
    m_sub = new Subscriber;
}

InterfaceManager::InterfaceManager(const QString& filename) {
    m_oracledb = new OracleDB(filename);
    m_pub = new Publisher;
    m_sub = new Subscriber;
}

InterfaceManager::~InterfaceManager() {
    if(m_protocol != nullptr) {
        delete m_protocol;
        m_protocol = nullptr;
    }
    if(m_conver != nullptr) {
        delete m_conver;
        m_conver = nullptr;
    }
    if(m_pub != nullptr) {
        delete m_pub;
        m_pub = nullptr;
    }
    if(m_sub != nullptr) {
        delete m_sub;
        m_sub = nullptr;
    }
}

VecPD InterfaceManager::data2Protocol(QString filename, QByteArray data) {
    m_protocol = new ParseProtocol(filename);
    m_protocol->ReadXmlProtocol();
    return m_protocol->ParsePacketData(data, data.size());
}

QByteArray InterfaceManager::protocol2Data(QString filename, QStringList rowdata) {
    m_conver = new ConvertData(filename, rowdata);
    return m_conver->ConvertNewData();
}

void InterfaceManager::sendMsg(QString ip, QString port, QByteArray content) {
    QUdpSocket udpsocekt;
    udpsocekt.writeDatagram(content, QHostAddress(ip), port.toShort());    // 向指定ip发送数据
}

void InterfaceManager::sendMulticastMsg(QString port, QByteArray content) {
    QUdpSocket multicast;
    multicast.writeDatagram(content, m_castaddr, port.toShort());          // 向组发送数据（组播）
}

void InterfaceManager::createReceiver(QString port, void (*func)(QByteArray&)) {
    QHash<QString, QVector<myfunction>>::iterator funcs = m_funcset.find(port);
    if(funcs != m_funcset.end())
    {
        if(!((funcs.value()).contains(func)))
            (funcs.value()).push_back(func);
    }
    else
    {
        m_funcset[port].push_back(func);
        m_receiver = new QUdpSocket;
        m_receiver->bind(QHostAddress::AnyIPv4, port.toShort(), QUdpSocket::ShareAddress);
        m_receiver->joinMulticastGroup(m_castaddr);    // 加入某个组播
        m_receiver->setSocketOption(QAbstractSocket::MulticastTtlOption, 18);    // 设置TTL
        connect(m_receiver, &QIODevice::readyRead, this, [=]() {
            QByteArray ba;
            while(m_receiver->hasPendingDatagrams())
            {
                ba.resize(m_receiver->pendingDatagramSize());
                m_receiver->readDatagram(ba.data(), ba.size());
                for(int i = 0; i < m_funcset[port].size(); ++i)
                {
                    (*(m_funcset[port][i]))(ba);
                }
            }
        });
    }
}

QVector<QVector<QVariant>> InterfaceManager::sqlQuery(const QString& sentence) {
    return m_oracledb->sqlQuery(sentence);
}

bool InterfaceManager::sqlOpt(const QString& sentence) {
    return m_oracledb->sqlOpt(sentence);
}

QSqlQuery InterfaceManager::getSqlQuery() {
    return m_oracledb->getSqlQuery();
}

void InterfaceManager::createTopic(const std::string& topic, bool reliable,
                                   bool redundancy, const int& priority) {
    m_pub->createTopic(topic, reliable, redundancy, priority);
}

void InterfaceManager::publish4Top(const std::string& topic, const TupMsg& tmsg) {
    m_pub->publish4Topic(topic, tmsg);
}

void InterfaceManager::deleteTopic(const std::string& topic) {
    m_pub->deleteTopic(topic);
}

void InterfaceManager::listenTopic(const std::string& topic, Func fun, bool reliable, bool redundancy) {
    m_sub->listenTopic(topic, fun, reliable, redundancy);
}

void InterfaceManager::cancelTopic(const std::string& topic) {
    m_sub->cancelTopic(topic);
}
